package com.xhsj.user.hr.system.service;

import com.alibaba.fastjson.JSONArray;
import com.xhsj.user.hr.base.BaseParam;
import com.xhsj.user.hr.process.base.BaseProcessService;
import com.xhsj.user.hr.process.dto.processDefinition.HandleAuditDto;
import com.xhsj.user.hr.process.hrLeaveProcess.mapper.TbHrApprovalLeaveApplyMapper;
import com.xhsj.user.hr.process.hrLeaveProcess.query.CompensatoryLeaveTimeQuery;
import com.xhsj.user.hr.process.hrLeaveProcess.service.TbHrApprovalLeaveTimeService;
import com.xhsj.user.hr.process.message.service.TbProjectMessageService;
import com.xhsj.user.hr.process.processDefinition.entity.TbGlobalApprovalHiTask;
import com.xhsj.user.hr.process.processDefinition.entity.TbGlobalApprovalTask;
import com.xhsj.user.hr.process.processDefinition.entity.TbGlobalWorkFlowNode;
import com.xhsj.user.hr.process.processDefinition.query.ProcessNodeQuery;
import com.xhsj.user.hr.process.processDefinition.service.TbGlobalApprovalHiTaskService;
import com.xhsj.user.hr.process.processDefinition.service.TbGlobalWorkFlowNodeService;
import com.xhsj.user.hr.process.query.ApprovalQuery;
import com.xhsj.user.security.entity.LoginUser;
import com.xhsj.user.hr.system.dto.HandoverAuditDto;
import com.xhsj.user.hr.system.entity.*;
import com.xhsj.user.hr.system.mapper.*;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xhsj.user.hr.system.vo.DimissionApplyAuditTaskVo;
import com.xhsj.user.hr.system.vo.LeaveTimeVo;
import com.xhsj.user.hr.userInfo.mapper.TbGlobalUserDetailMapper;
import com.xhsj.user.utils.DateUtils;
import com.xhsj.user.utils.MessageConstant;
import com.xhsj.user.utils.StringUtils;
import com.xhsj.user.utils.UserUtils;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.io.Serializable;
import java.util.concurrent.CompletableFuture;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
/**
 * <p>
 * hr流程-离职交接申请表 服务实现类
 * </p>
 *
 * @author suxiaolin
 * @since Sep 9, 2020 3:32:18 PM
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
//@CacheConfig(cacheNames = "TbHrApprovalDimissionHandoverApply")
public class TbHrApprovalDimissionHandoverApplyService extends BaseProcessService<TbHrApprovalDimissionHandoverApplyMapper, TbHrApprovalDimissionHandoverApply> {
    @Autowired
    private TbHrApprovalDimissionHandoverApplyMapper dao;

    @Autowired
    private TbHrApprovalDimissionApplyMapper tbHrApprovalDimissionApplyMapper;

    @Autowired
    private TbHrApprovalDimissionHandoverMatterService tbHrApprovalDimissionHandoverMatterService;

    @Autowired
    private TbHrApprovalDimissionHandoverMatterMapper tbHrApprovalDimissionHandoverMatterMapper;

    @Autowired
    private TbHrApprovalDimissionHandoverGoodsService tbHrApprovalDimissionHandoverGoodsService;
    @Autowired
    private TbHrApprovalDimissionHandoverGoodsMapper tbHrApprovalDimissionHandoverGoodsMapper;

    @Autowired
    private TbGlobalWorkFlowNodeService tbGlobalWorkFlowNodeService;

    @Autowired
    private TbGlobalUserMapper tbGlobalUserMapper;
    @Autowired
    private TbProjectMessageService tbProjectMessageService;

    @Autowired
    private TbHrApprovalLeaveTimeService tbHrApprovalLeaveTimeService;
    // 流程历史
    @Autowired
    private TbGlobalApprovalHiTaskService processHiTaskService;

    @Autowired
    private TbHrLeaveUsableLengthService tbHrLeaveUsableLengthService;

    @Autowired
    private TbGlobalUserDetailMapper tbGlobalUserDetailMapper;

	/**
	 * 保存
	 * @author suxiaolin
	 * @date Sep 9, 2020 3:32:18 PM
	 */
    @Override
    //@CacheEvict(cacheNames="TbHrApprovalDimissionHandoverApply", allEntries=true)
    public boolean save(TbHrApprovalDimissionHandoverApply entity) {
        return super.save(entity);
    }

	/**
	 * 通过id获取数据
	 * @author suxiaolin
	 * @date Sep 9, 2020 3:32:18 PM
	 */
    @Override
    //@Cacheable(key = "#id",sync = true)
    public TbHrApprovalDimissionHandoverApply getById(Serializable id) {
        return super.getById(id);
    }

	/**
	 * 通过id删除数据
	 * @author suxiaolin
	 * @date Sep 9, 2020 3:32:18 PM
	 */
    @Override
    //@CacheEvict(cacheNames="TbHrApprovalDimissionHandoverApply", allEntries=true)
    public boolean removeById(Serializable id) {
        return super.removeById(id);
    }

	/**
	 * 批量删除数据
	 * @author suxiaolin
	 * @date Sep 9, 2020 3:32:18 PM
	 */
    //@CacheEvict(cacheNames="SysDict", allEntries=true)
    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        return super.removeByIds(idList);
    }

	/**
	 * 分页查询数据
	 * @author suxiaolin
	 * @date Sep 9, 2020 3:32:18 PM
	 */
    //@Cacheable(key = "#data",sync = true)
    public IPage<TbHrApprovalDimissionHandoverApply> selectPage(Map<String,Object> data) {
        int currentPage=1;
        if (!Objects.isNull(data.get("page"))) {
            currentPage=(Integer) data.get("page");
        }
        int pageSize=20;
        if (!Objects.isNull(data.get("size"))) {
            pageSize=(Integer) data.get("size");
        }

        TbHrApprovalDimissionHandoverApply entity = JSON.parseObject(JSON.toJSONString(data), TbHrApprovalDimissionHandoverApply.class);
        Page<TbHrApprovalDimissionHandoverApply> page = new Page(currentPage,pageSize);
        QueryWrapper<TbHrApprovalDimissionHandoverApply> wrapper = new QueryWrapper(entity);
        return super.selectPage(page, wrapper);
    }

	/**
	 * 查询所有数据
	 * @author suxiaolin
	 * @date Sep 9, 2020 3:32:18 PM
	 */
    @Override
    //@Cacheable(value = "TbHrApprovalDimissionHandoverApply",sync = true)
    public List<TbHrApprovalDimissionHandoverApply> selectAll() {
        return super.selectAll();
    }


    /**
     * 保存数据
     * @author 苏小林
     * @date 2020/9/9 17:28
     * @param: entity
     */
    public void saveData(TbHrApprovalDimissionHandoverApply entity) throws Exception {

        boolean save = super.save(entity);
        if (save) {
            List<String> matters = entity.getMatters();
            for (String matter : matters) {
                TbHrApprovalDimissionHandoverMatter handoverMatter = new TbHrApprovalDimissionHandoverMatter();
                handoverMatter.setApplyId(entity.getId());
                handoverMatter.setMatters(matter);
                boolean save1 = tbHrApprovalDimissionHandoverMatterService.save(handoverMatter);
                if (!save1) {
                    throw new Exception("tbHrApprovalDimissionHandoverMatter保存失败");
                }
            }
        } else {
            throw new Exception("tbHrApprovalDimissionHandoverMatter保存失败");
        }

        Long dimissionApplyId = entity.getDimissionApplyId();

        TbHrApprovalDimissionApply dimissionApply = new TbHrApprovalDimissionApply();
        dimissionApply.setId(dimissionApplyId);
        dimissionApply.setIsHandover(1);
        int i = tbHrApprovalDimissionApplyMapper.updateById(dimissionApply);
        if (i == 0) {
            throw new Exception("tbHrApprovalDimissionApply保存失败");
        }

        // 启动流程
        this.startProcess(entity);
    }

    /**
     * 启动流程
     * @author 苏小林
     * @date 2020/9/8 13:46
     * @param: data
     */
    private void startProcess(TbHrApprovalDimissionHandoverApply entity) throws Exception {
        LoginUser loginAppUser = UserUtils.getLoginAppUser();
        Long userId = loginAppUser.getUserId();
        HandleAuditDto handleAuditDto = new HandleAuditDto(entity.getId(), userId, userId, 7);
        // 流程启动
        ProcessNodeQuery processNodeQuery = super.startHandleAudit(handleAuditDto, entity.getDepartmentId());
        entity.setBusinessId(handleAuditDto.getBusinessId());
        // 修改申请信息
        this.updateInfoById(entity,processNodeQuery);

        // 发送消息
        ApprovalQuery approvalQuery =
                new ApprovalQuery(handleAuditDto.getDataId(), MessageConstant.MSG_5, processNodeQuery.getUserId(),
                        processNodeQuery.getRoleIds(), 4, UserUtils.getLoginAppUser().getUserId(),entity.getApplyUserName());
        this.sendMessage(approvalQuery);
    }

    public void sendMessage(ApprovalQuery approvalQuery) {
        //保存消息
        CompletableFuture<Void> f = CompletableFuture.runAsync(() -> {
            tbProjectMessageService.sendMessageCommon(approvalQuery);
        });
    }

    /**
     * 修改申请信息
     * @author 苏小林
     * @date 2020/9/8 13:52
     * @param: entity
     * @param: processNodeQuery
     */
    private void updateInfoById(TbHrApprovalDimissionHandoverApply entity, ProcessNodeQuery processNodeQuery) {
        entity.setNodeId(processNodeQuery.getNodeId());
        entity.setNodeName(processNodeQuery.getNodeName());
        entity.setUpdateBy(UserUtils.getLoginAppUser().getUserId());
        entity.setUpdateDate(new Date());
        this.updateById(entity);
    }

    /**
     * 查询待审核任务
     * @author 苏小林
     * @date 2020/9/9 18:32
     * @param: baseParam
     * @return: com.baomidou.mybatisplus.core.metadata.IPage<com.xhsj.user.hr.system.vo.DimissionApplyAuditTaskVo>
     */
    public IPage<DimissionApplyAuditTaskVo> findDimissionHandoverApplyRunTask(BaseParam data) {
        Page<TbHrApprovalDimissionApply> page = new Page(data.getPage(),data.getSize());

        Long userId = UserUtils.getLoginAppUser().getUserId();
        List<Long> roleIds = tbGlobalUserMapper.getRoleIdsByUserId(userId);
        return dao.findDimissionHandoverApplyRunTask(page,userId,roleIds);
    }

    /**
     * 查询历史任务
     * @author 苏小林
     * @date 2020/9/9 18:33
     * @param: baseParam
     * @return: com.baomidou.mybatisplus.core.metadata.IPage<com.xhsj.user.hr.system.vo.DimissionApplyAuditTaskVo>
     */
    public IPage<DimissionApplyAuditTaskVo> findDimissionHandoverApplyHiTask(BaseParam data) {
        Page<TbHrApprovalDimissionApply> page = new Page(data.getPage(),data.getSize());

        Long userId = UserUtils.getLoginAppUser().getUserId();
        return dao.findDimissionHandoverApplyHiTask(page,userId);
    }

    /**
     * 通过id查询数据
     * @author 苏小林
     * @date 2020/9/10 9:59
     * @param: id
     * @return: com.xhsj.user.hr.system.vo.GetHandOverDataInfoByIdVo
     */
    public TbHrApprovalDimissionHandoverApply getDataInfoById(Long id) throws ParseException {
        TbHrApprovalDimissionHandoverApply byId = this.getById(id);

        if (byId != null) {
            String roleKeyName = tbGlobalWorkFlowNodeService.getRoleByBusinessIdAndNodeId(byId.getBusinessId(),byId.getNodeId());
            byId.setCurrAuditRole(roleKeyName);
            List<String> list = tbHrApprovalDimissionHandoverMatterService.getMattersByApplyId(id);
            byId.setMatters(list);
            List<String> list1 = tbHrApprovalDimissionHandoverGoodsService.getGoodsByApplyId(id);
            byId.setGoods(list1);

            /*查询加班本月加班情况*/
            Long applyUserId = byId.getApplyUserId();
            // 离职申请id
            Long dimissionApplyId = byId.getDimissionApplyId();
            TbHrApprovalDimissionApply tbHrApprovalDimissionApply = tbHrApprovalDimissionApplyMapper.selectById(dimissionApplyId);
            // 离职时间
            LocalDate localDate = DateUtils.date2LocalDate(tbHrApprovalDimissionApply.getLeaveDate());
            //这个月的第一天
            LocalDate monthStart = localDate.with(TemporalAdjusters.firstDayOfMonth());
            LocalDate monthEnd = localDate.with(TemporalAdjusters.lastDayOfMonth());
            //这个月的最后一天
            System.err.println(monthStart);
            List<LeaveTimeVo> leaveTimeList = tbHrApprovalLeaveTimeService.getCurrentLeaveTimeByApplyUserId(applyUserId,monthStart,monthEnd);
            byId.setLeave(leaveTimeList);

            if (StringUtils.isBlank(byId.getBankAccount())) {
                /*获取用户银行卡号*/
                String bankAccount = tbGlobalUserDetailMapper.getBankAccountByUserId(applyUserId);
                byId.setBankAccount(bankAccount);
            }



            /*查询年假剩余和加班剩余*/
            CompensatoryLeaveTimeQuery overTimeUsableLength = tbHrLeaveUsableLengthService.getOverTimeUsableLength(applyUserId, localDate);
            if (overTimeUsableLength != null) {
                byId.setAnnualLeaveUsable(overTimeUsableLength.getAnnualLeaveUsable());
                byId.setSurplusTime(overTimeUsableLength.getSurplusTime());
            }

        }

        return byId;
    }

    /**
     * 流程审核
     * @author 苏小林
     * @date 2020/9/10 10:29
     * @param: handleAuditDto
     */
    public void processAudit(HandoverAuditDto handoverAuditDto) throws Exception {
        TbHrApprovalDimissionHandoverApply tbHrApprovalDimissionHandoverApply = handoverAuditDto.getApply();
        // 获取id
        Long id = handoverAuditDto.getDataId();
        TbHrApprovalDimissionHandoverApply byId = this.getById(id);
//        if (byId != null) {
//            Integer needApplyConfirm = byId.getNeedApplyConfirm();
//            Integer applyPartFinish = byId.getApplyPartFinish();
//
//            // 需要申请人确认 但申请人还未确认
//            if (needApplyConfirm == 0 && applyPartFinish == 1) {
//                throw new Exception("请等待申请人确认后点击操作");
//            }
//        }
//        Integer needApplyConfirm = null;
        if (tbHrApprovalDimissionHandoverApply != null) {
            List<String> goods = tbHrApprovalDimissionHandoverApply.getGoods();
            if (goods != null && goods.size() >0) {
                for (String good : goods) {
                    TbHrApprovalDimissionHandoverGoods handoverGoods = new TbHrApprovalDimissionHandoverGoods();
                    handoverGoods.setGoods(good);
                    handoverGoods.setApplyId(handoverAuditDto.getDataId());
                    tbHrApprovalDimissionHandoverGoodsService.save(handoverGoods);
                }
            }
            this.updateById(tbHrApprovalDimissionHandoverApply);
//            needApplyConfirm = tbHrApprovalDimissionHandoverApply.getNeedApplyConfirm();
        }
        ProcessNodeQuery processNodeQuery = this.handleAudit(handoverAuditDto);
        TbHrApprovalDimissionHandoverApply entity = new TbHrApprovalDimissionHandoverApply();
        entity.setId(handoverAuditDto.getDataId());

        entity.setBusinessId(handoverAuditDto.getBusinessId());
        // 修改申请信息
        this.updateInfoById(entity,processNodeQuery);

        // 发送消息
        ApprovalQuery approvalQuery =
                new ApprovalQuery(handoverAuditDto.getDataId(), MessageConstant.MSG_5, processNodeQuery.getUserId(),
                        processNodeQuery.getRoleIds(), 4, UserUtils.getLoginAppUser().getUserId(),byId == null?"":byId.getApplyUserName());
        this.sendMessage(approvalQuery);

//        if (needApplyConfirm !=null && needApplyConfirm == 0) {
//            // 发送消息
//            SmsApprovalQuery approvalQuery =
//                    new SmsApprovalQuery(handoverAuditDto.getDataId(), "我的申请-交接确认", Arrays.asList(tbHrApprovalDimissionHandoverApply.getApplyUserId()),
//                            null, 4, UserUtils.getLoginAppUser().getUserId());
//            this.sendMessage(approvalQuery);
//        } else {
//
//        }

    }


    @Override
    public ProcessNodeQuery handleAudit(HandleAuditDto data) throws Exception {
        // 得到节点id和几点名称
        ProcessNodeQuery processNodeVo = new ProcessNodeQuery();
        Object roleIds = null;
        Object auditUserId = null;
        // 中deal_with字段 0 通过 1 退回 2 重要
        try {
            Object nextNodeId =null;
            // 节点名称
            String nodeName = null;
            if (data.getStatus()== 1) {
                // 查询初始流程节点
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("business_id",data.getBusinessId());
                queryWrapper.eq("approve_order_no",1);
                TbGlobalWorkFlowNode firstProcessNodeIdQuery = tbGlobalWorkFlowNodeService.getOne(queryWrapper);
                nextNodeId = firstProcessNodeIdQuery.getApproveOrderNo();
                nodeName = firstProcessNodeIdQuery.getTaskName();
                data.setUserId(Arrays.asList(String.valueOf(data.getProposerId()).split(",")));
            }else if(data.getStatus()== 0){
                // 查询下一节点
                Map<String, Object> map = super.getNextNode(data.getNodeId(),data.getBusinessId());
                nextNodeId = map.get("nextNodeId");
                nodeName = String.valueOf(map.get("nextNodeName"));
                if ("申请人确认".equals(nodeName)) {
                    data.setUserId(Arrays.asList(data.getProposerId()));
                } else {
                    Object roleId = map.get("roleId");
                    if (!Objects.isNull(roleId)) {
                        data.setRoleIds(Arrays.asList(String.valueOf(roleId).split(",")));
                    }
                }
            }
            // 获取下一个节点的用户名
            String handler = super.getHandler(data);
            TbGlobalApprovalTask processTask = null;
            if (!Objects.isNull(nextNodeId) && StringUtils.isNotBlank(nextNodeId)) {
                // 用户
                if (!Objects.isNull(data.getUserId())) {
                    auditUserId = data.getUserId();
                    List<Long> split = JSONArray.parseArray(String.valueOf(data.getUserId()), Long.class);
                    for (Long s : split) {
                        // 审核参数转正在执行流程表参数
                        data.setUserId(null);
                        processTask = StringUtils.toJavaBean(data, TbGlobalApprovalTask.class);
                        processTask.setUserId(s);
                        processTask.setNodeId(StringUtils.toLong(nextNodeId));
                        processTask.setHandler(handler);
                        // 添加下一个节点执行任务
                        super.savaRunAndHisTask(processTask,data.getOpinionText(),nodeName);
                    }
                }
                // 角色
                if (!Objects.isNull(data.getRoleIds())) {
                    roleIds = data.getRoleIds();
                    List<Long> split1 = JSONArray.parseArray(String.valueOf(data.getRoleIds()), Long.class);
                    for (Long s : split1) {
                        // 审核参数转正在执行流程表参数
                        data.setRoleIds(null);
                        processTask = StringUtils.toJavaBean(data, TbGlobalApprovalTask.class);
                        processTask.setRoleId(s);
                        processTask.setNodeId(StringUtils.toLong(nextNodeId));
                        processTask.setHandler(handler);
                        // 添加正在执行任务
                        super.savaRunAndHisTask(processTask,data.getOpinionText(),nodeName);
                    }
                }
            }

            long nodeId = StringUtils.toLong(nextNodeId);
            if ("完结".equals(nodeName)) { // 将完结节点添加到历史表
                Long userId = UserUtils.getLoginAppUser().getUserId();
                TbGlobalApprovalHiTask tbGlobalApprovalHiTask = new TbGlobalApprovalHiTask(data.getBusinessId(),data.getDataId(),nodeId,0,nodeName,userId,new Date(),userId,new Date());
                processHiTaskService.save(tbGlobalApprovalHiTask);
            }
            // 修改目前执行的任务+保存意见
            super.updateRunTask(data);
            // 节点id
            LoginUser loginAppUser = UserUtils.getLoginAppUser();
            Long userId = loginAppUser.getUserId();
            processNodeVo.setRoleIds(data.getRoleIds());
            processNodeVo.setUserId(data.getUserId());
            processNodeVo.setCurrentUserId(userId);
            processNodeVo.setNodeId(nodeId);
            processNodeVo.setUserId(auditUserId);
            processNodeVo.setRoleIds(roleIds);
            processNodeVo.setNodeName(nodeName);
            if (data.getStatus()== 3){
                processNodeVo.setNodeName("作废");
                processNodeVo.setNodeId(0);
                processNodeVo.setDelFlag(1);
            }
        } catch (Exception e) {
            log.error("添加流程失败", e);
            throw new Exception(e);
        }
        return processNodeVo;
    }

    /**
     * 申请人确认
     * @author 苏小林
     * @date 2020/9/11 13:36
     * @param: id
     * @param: applyConfirmOpinion
     */
    public void applyConfirm(Long id, String applyConfirmOpinion) {
        dao.updateApplyConfirm(id,applyConfirmOpinion);
    }


    public void updateData(TbHrApprovalDimissionHandoverApply apply) {
        List<String> goods = apply.getGoods();
        if (goods != null && goods.size() >0) {
            tbHrApprovalDimissionHandoverGoodsMapper.delByApplyId(apply.getId());
            for (String good : goods) {
                TbHrApprovalDimissionHandoverGoods handoverGoods = new TbHrApprovalDimissionHandoverGoods();
                handoverGoods.setGoods(good);
                handoverGoods.setApplyId(apply.getId());
                tbHrApprovalDimissionHandoverGoodsService.save(handoverGoods);
            }
        }
        this.updateById(apply);

    }
}
